﻿using System;
using System.IO;
using System.Text;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace iPhoneUI
{
    public static class IImageExtensions
    {
        public static Size Size(this IImage image)
        {
            Debug.Assert(image != null);

            ImageInfo info;
            image.GetImageInfo(out info);
            return new Size((int)info.Width, (int)info.Height);
        }
    }

    public static class Shortcut
    {
        public static Icon GetIcon(string file)
        {
            return GetIcon(file, NativeMethods.SHGFI_LARGEICON);
        }

        public static Icon GetSmallIcon(string file)
        {
            return GetIcon(file, NativeMethods.SHGFI_SMALLICON);
        }

        private static Icon GetIcon(string file, uint size)
        {
            SHFILEINFO shinfo = new SHFILEINFO();
            IntPtr ret = NativeMethods.SHGetFileInfo(file, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), NativeMethods.SHGFI_ICON | size);

            if (ret != IntPtr.Zero)
            {
                Icon icon = Icon.FromHandle(shinfo.hIcon);
                NativeMethods.DestroyIcon(shinfo.hIcon);
                return icon;
            }

            return null;
        }
    }

    public static class PhoneInfo
    {
        public static string GetPhoneNumber()
        {
            SMS_ADDRESS address = new SMS_ADDRESS();
            if (NativeMethods.SmsGetPhoneNumber(ref address) == 0)
                return address.ptsAddress;

            // if the above didn't work return OwnerPhoneNumber property (only set if the user sets it)
            return Microsoft.WindowsMobile.Status.SystemState.OwnerPhoneNumber;
        }
    }

    static class NativeMethods
    {
        public const byte AC_SRC_OVER = 0;
        public const byte AC_SRC_ALPHA = 1;

        public const int MAX_PATH = 260;

        public const uint SHGFI_ICON = 0x100;
        public const uint SHGFI_LARGEICON = 0x0;    // 'Large icon
        public const uint SHGFI_SMALLICON = 0x1;    // 'Small icon

        [DllImport("coredll.dll", SetLastError = true)]
        public extern static Int32 AlphaBlend(IntPtr hdcDest, Int32 xDest, Int32 yDest, Int32 cxDest, Int32 cyDest, IntPtr hdcSrc, Int32 xSrc, Int32 ySrc, Int32 cxSrc, Int32 cySrc, BlendFunction blendFunction);

        [DllImport("coredll.dll", SetLastError = true)]
        public extern static bool SHGetShortcutTarget(string szShortcut, StringBuilder szTarget, int cbMax);

        [DllImport("coredll.dll", SetLastError = true)]
        public extern static IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);

        [DllImport("coredll.dll", SetLastError = true)]
        public extern static bool DestroyIcon(IntPtr hIcon);

        [DllImport("sms.dll")]
        public static extern int SmsGetPhoneNumber(ref SMS_ADDRESS psmsaAddress);
    }

    enum SMS_ADDRESS_TYPE
    {
        SMSAT_UNKNOWN = 0,
        SMSAT_INTERNATIONAL,
        SMSAT_NATIONAL,
        SMSAT_NETWORKSPECIFIC,
        SMSAT_SUBSCRIBER,
        SMSAT_ALPHANUMERIC,
        SMSAT_ABBREVIATED
    }

    [StructLayout(LayoutKind.Sequential)]
    struct SMS_ADDRESS
    {
        public SMS_ADDRESS_TYPE smsatAddressType;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string ptsAddress;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct SHFILEINFO
    {
        public IntPtr hIcon;
        public IntPtr iIcon;
        public uint dwAttributes;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NativeMethods.MAX_PATH)]
        public string szDisplayName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
        public string szTypeName;
    }

    struct BlendFunction
    {
        public byte BlendOp;
        public byte BlendFlags;
        public byte SourceConstantAlpha;
        public byte AlphaFormat;
    }

    // Pulled from gdipluspixelformats.h in the Windows Mobile 5.0 Pocket PC SDK
    public enum PixelFormatID : int
    {
        PixelFormatIndexed = 0x00010000,  // Indexes into a palette
        PixelFormatGDI = 0x00020000,      // Is a GDI-supported format
        PixelFormatAlpha = 0x00040000,    // Has an alpha component
        PixelFormatPAlpha = 0x00080000,   // Pre-multiplied alpha
        PixelFormatExtended = 0x00100000, // Extended color 16 bits/channel
        PixelFormatCanonical = 0x00200000,
        PixelFormatUndefined = 0,
        PixelFormatDontCare = 0,
        PixelFormat1bppIndexed = (1 | (1 << 8) | PixelFormatIndexed | PixelFormatGDI),
        PixelFormat4bppIndexed = (2 | (4 << 8) | PixelFormatIndexed | PixelFormatGDI),
        PixelFormat8bppIndexed = (3 | (8 << 8) | PixelFormatIndexed | PixelFormatGDI),
        PixelFormat16bppRGB555 = (5 | (16 << 8) | PixelFormatGDI),
        PixelFormat16bppRGB565 = (6 | (16 << 8) | PixelFormatGDI),
        PixelFormat16bppARGB1555 = (7 | (16 << 8) | PixelFormatAlpha | PixelFormatGDI),
        PixelFormat24bppRGB = (8 | (24 << 8) | PixelFormatGDI),
        PixelFormat32bppRGB = (9 | (32 << 8) | PixelFormatGDI),
        PixelFormat32bppARGB = (10 | (32 << 8) | PixelFormatAlpha | PixelFormatGDI | PixelFormatCanonical),
        PixelFormat32bppPARGB = (11 | (32 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatGDI),
        PixelFormat48bppRGB = (12 | (48 << 8) | PixelFormatExtended),
        PixelFormat64bppARGB = (13 | (64 << 8) | PixelFormatAlpha | PixelFormatCanonical | PixelFormatExtended),
        PixelFormat64bppPARGB = (14 | (64 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatExtended),
        PixelFormatMax = 15
    }

    // Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
    public enum BufferDisposalFlag : int
    {
        BufferDisposalFlagNone,
        BufferDisposalFlagGlobalFree,
        BufferDisposalFlagCoTaskMemFree,
        BufferDisposalFlagUnmapView
    }

    // Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
    public enum InterpolationHint : int
    {
        InterpolationHintDefault,
        InterpolationHintNearestNeighbor,
        InterpolationHintBilinear,
        InterpolationHintAveraging,
        InterpolationHintBicubic
    }

    // Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
    [StructLayout(LayoutKind.Sequential)]
    public struct ImageInfo
    {
        // I am being lazy here, I don't care at this point about the RawDataFormat GUID
        public uint GuidPart1;
        public uint GuidPart2;
        public uint GuidPart3;
        public uint GuidPart4;
        public PixelFormatID pixelFormat;
        public uint Width;
        public uint Height;
        public uint TileWidth;
        public uint TileHeight;
        public double Xdpi;
        public double Ydpi;
        public uint Flags;
    }

    // Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
    [ComImport, Guid("327ABDA7-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [ComVisible(true)]
    public interface IImagingFactory
    {
        uint CreateImageFromStream(); // This is a place holder
        uint CreateImageFromFile(string filename, out IImage image);
        // We need the MarshalAs attribute here to keep COM interop from sending the buffer down as a Safe Array.
        uint CreateImageFromBuffer([MarshalAs(UnmanagedType.LPArray)] byte[] buffer, uint size, BufferDisposalFlag disposalFlag, out IImage image);
        uint CreateNewBitmap();            // This is a place holder
        uint CreateBitmapFromImage();      // This is a place holder
        uint CreateBitmapFromBuffer();     // This is a place holder
        uint CreateImageDecoder();         // This is a place holder
        uint CreateImageEncoderToStream(); // This is a place holder
        uint CreateImageEncoderToFile();   // This is a place holder
        uint GetInstalledDecoders();       // This is a place holder
        uint GetInstalledEncoders();       // This is a place holder
        uint InstallImageCodec();          // This is a place holder
        uint UninstallImageCodec();        // This is a place holder
    }

    // Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
    [ComImport, Guid("327ABDA9-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [ComVisible(true)]
    public interface IImage
    {
        uint GetPhysicalDimension(out Size size);
        uint GetImageInfo(out ImageInfo info);
        uint SetImageFlags(uint flags);
        // "Correct" declaration: uint Draw(IntPtr hdc, ref Rectangle dstRect, ref Rectangle srcRect);
        uint Draw(IntPtr hdc, ref Rectangle dstRect, IntPtr NULL);
        uint PushIntoSink(); // This is a place holder
        uint GetThumbnail(uint thumbWidth, uint thumbHeight, out IImage thumbImage);
    }
}
